package com.lemon.core.base.jwt;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.lemon.core.base.util.ServletUtils;
import com.lemon.core.base.constant.GlobalConstants;
import com.lemon.core.base.constant.SecurityConstants;
import com.lemon.core.base.exception.ServiceException;
import com.lemon.core.base.jwt.model.AuthInfo;
import com.nimbusds.jose.JWSObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * JWT工具类
 *
 * @author pan
 * @since 2018-05-25
 */
@Slf4j
public class JwtUtils {

    @SneakyThrows
    public static JSONObject getJwtPayload() {
        String payload = ServletUtils.getHttpServletRequest().getHeader(SecurityConstants.JWT_PAYLOAD_KEY);
        if (null == payload) {
            throw new ServiceException("请传入认证头");
        }
        return JSONUtil.parseObj(URLDecoder.decode(payload, StandardCharsets.UTF_8.name()));
    }

    @SneakyThrows
    public static AuthInfo getAuthInfo(String token) {
        if (null == token) {
            throw new ServiceException("请传入认证头");
        }
        token = StrUtil.replaceIgnoreCase(token, SecurityConstants.JWT_PREFIX, Strings.EMPTY);
        String payload = StrUtil.toString(JWSObject.parse(token).getPayload());
        JSONObject jsonObject = JSONUtil.parseObj(payload);
        String jti = jsonObject.getStr(SecurityConstants.JWT_JTI);

        List<String> roles = null;
        if (jsonObject.containsKey(SecurityConstants.JWT_AUTHORITIES_KEY)) {
            roles = jsonObject.getJSONArray(SecurityConstants.JWT_AUTHORITIES_KEY).toList(String.class);
        }
        return AuthInfo.builder()
                .jti(jti)
                .tenantId(jsonObject.getStr(SecurityConstants.TENANT_ID_KEY))
                .userId(jsonObject.getLong(SecurityConstants.USER_ID_KEY))
                .username(jsonObject.getStr(SecurityConstants.USER_NAME_KEY))
                .authorities(roles)
                .accessToken(token).build();
    }

    /**
     * 解析JWT获取用户ID
     *
     * @return
     */
    public static Long getUserId() {
        return getJwtPayload().getLong(SecurityConstants.USER_ID_KEY);
    }

    /**
     * 解析JWT获取获取用户名
     *
     * @return
     */
    public static String getUsername() {
        return getJwtPayload().getStr(SecurityConstants.USER_NAME_KEY);
    }

    /**
     * JWT获取用户角色列表
     *
     * @return 角色列表
     */
    public static List<String> getRoles() {
        List<String> roles = null;
        JSONObject payload = getJwtPayload();
        if (payload.containsKey(SecurityConstants.JWT_AUTHORITIES_KEY)) {
            roles = payload.getJSONArray(SecurityConstants.JWT_AUTHORITIES_KEY).toList(String.class);
        }
        return roles;
    }

    /**
     * JWT获取用户角色列表
     *
     * @return 角色列表
     */
    public static boolean isRootRole() {
        List<String> roles = getRoles();
        if (CollUtil.isEmpty(roles)) {
            return false;
        }
        return roles.contains(GlobalConstants.ROOT_ROLE_CODE);
    }
}
